/* 
 *	Copyright 2014  Yanqing Wu
 *		email: yqwu_yqwu@126.com
 *
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
*/

#pragma once

#include <map>
/*
 *	The config file is using strings, while the internal code is using enums
 *	The class "CStdCtrlSkin_Enums" is created to convert strings to enums, just
 *	like the "Parse" method in C#.
 *
 *	Each enum has an "Err" at end, for error indicating
 */

enum class CStdCtrlSkin_EnumSticky
{
	C = 0,
	N = 1,
	S = 2,
	W = 4,
	E = 8,
	UNDEF = 16
};

enum class CStdCtrlSkin_EnumExpand
{
	X = 1,
	Y = 2
};

enum class CStdCtrlSkin_EnumAttrib
{
	//	Cell
	NAME,
	WIDTH,
	HEIGHT,
	PADX,
	PADY,
	COLSPAN,
	ROWSPAN,
	STICKY,
	//	Row
	//		HEIGHT,
	WEIGHT,
	// Table
	//		PADX,
	//		PADY,
	//		WEIGHT,
	EXPAND,
	//	Colweight
	COL,
	//		WEIGHT,
	//	BG
	BACKCOLOR,
	TYPE,
	//	Gradiant color
	COLOR1,
	COLOR2,
	ALPHA,
	//	Gradiant dir
	DIRECTION,
	//	BG image attribute
	FILEPATH,
	DRAWMODE,
	TRANS,
	SRCORIGIN,
	//	BG cell border
	BBOX,
	//	Window
	//	NAME,
	//	Root element
	VERSION,
	//	Done
	ERR
};

enum class CStdCtrlSkin_EnumSubNode
{
	//	Row
	CELL,
	//	Table
	ROW,
	COLCONFIG,
	//	BG
	GRADIANT,
	IMAGE,
	//	Window
	BG,
	TABLE,
	//	Root element
	WINDOW,
	//	Done
	ERR
};

enum class CStdCtrlSkin_EnumBgType
{
	GRADIENT,
	IMAGE,
	ERR
};

enum class CStdCtrlSkin_EnumGradDir
{
	HORIZONTAL,
	VERTICAL,
	SLASH,
	BACKSLASH
};

enum class CStdCtrlSkin_EnumImgMode
{
	CENTER,
	TILE,
	STRETCH
};

enum class CStdCtrlSkin_EnumDump
{
	TABLE_RECT = 0x01,
	TABLE_MIN_GRID = 0x02,
	TABLE_SHOW_GRID =0x04,
	CELL_RECT = 0x08,
	CELL_ITEM_RECT = 0x10,
	OTHER_ATTRIB = 0x20,
	CELL_ATTRIB_INST = 0x40,
	CELL_ATTRIB_FINAL = 0x80,
	BG = 0x100,
	ALL = 0xFFFF
};

class CStdCtrlSkin_Enums
{
public:
	CStdCtrlSkin_Enums(void);
	virtual ~CStdCtrlSkin_Enums(void);

	template <typename Type>
	bool ParseCombo(Type& oType, CString str)
	{
		Type charType;
		CStringA strA(str);
		int iResult=0, iCharType;
		auto pStr = strA.GetString();
		auto length = strA.GetLength();
		auto pEnum = StdCtrlSkinTool_GetEnum();
		CString charStr;
		for(int i=0; i<length; i++)
		{
			charStr.Format(_T("%c"), *(pStr+i));
			auto correct = pEnum->Parse(charType, charStr);
			if ( correct )
			{
				iCharType = (int)charType;
				iResult |= iCharType;
			}
		}
		oType = (Type)iResult;
		return true;
	}
	//	Implement the Parse method in C#
protected:
	std::map<CStdCtrlSkin_EnumSticky, CString> m_sticky_list;
	std::map<CStdCtrlSkin_EnumExpand, CString> m_expand_list;
	std::map<CStdCtrlSkin_EnumAttrib, CString> m_attrib_list;
	std::map<CStdCtrlSkin_EnumSubNode, CString> m_subnode_list;
	std::map<CStdCtrlSkin_EnumBgType, CString> m_bgtype_list;
	std::map<CStdCtrlSkin_EnumGradDir, CString> m_graddir_list;
	std::map<CStdCtrlSkin_EnumImgMode, CString> m_imgmode_list;

public:
	template <typename Type>
	bool Parse(Type& oType, const CString string)
	{
		auto stringList = GetEnumStringList(oType);
		for(auto i : *stringList)
		{
			auto type = i.first;
			auto value = i.second;
			if ( string.Compare(value)==0 )
			{
				oType = type;
				return true;
			}
		}
		return false;
	}
	//	Implement the ToString method in C#
	template <typename Type>
	CString ToString(Type enumValue)
	{
		auto stringList = GetEnumStringList(enumValue);
		if ( stringList->find(enumValue)==stringList->end() )
			return _T("");
		return (*stringList)[enumValue];
	}
	template <typename Type>
	CString ComboToString(Type enumValue)
	{
		UINT intValue = 1, bits = 0;
		CString result;
		while(bits<31)
		{
			if ( ((int)enumValue) & intValue )
			{
				Type current = (Type)intValue;
				result += ToString(current);
			}
			intValue = intValue << 1;
			bits ++;
		}
		return result;

	}

	std::map<CStdCtrlSkin_EnumSticky, CString>* GetEnumStringList(CStdCtrlSkin_EnumSticky)
	{
		return &m_sticky_list;
	}
	std::map<CStdCtrlSkin_EnumExpand, CString>* GetEnumStringList(CStdCtrlSkin_EnumExpand)
	{
		return &m_expand_list;
	}
	std::map<CStdCtrlSkin_EnumAttrib, CString>* GetEnumStringList(CStdCtrlSkin_EnumAttrib)
	{
		return &m_attrib_list;
	}
	std::map<CStdCtrlSkin_EnumSubNode, CString>* GetEnumStringList(CStdCtrlSkin_EnumSubNode)
	{
		return &m_subnode_list;
	}
	std::map<CStdCtrlSkin_EnumBgType, CString>* GetEnumStringList(CStdCtrlSkin_EnumBgType)
	{
		return &m_bgtype_list;
	}
	std::map<CStdCtrlSkin_EnumGradDir, CString>* GetEnumStringList(CStdCtrlSkin_EnumGradDir)
	{
		return &m_graddir_list;
	}
	std::map<CStdCtrlSkin_EnumImgMode, CString>* GetEnumStringList(CStdCtrlSkin_EnumImgMode)
	{
		return &m_imgmode_list;
	}
};

